import { Injectable } from '@nestjs/common';
import { CreateEventDto } from './dto/create-event.dto';
import { Event } from './entities/event.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import logger from 'src/common/utils/log';
import { EventStatusEnum, StageStatusEnum } from 'src/common/constant/enums';

@Injectable()
export class EventService {
  constructor(
    @InjectRepository(Event)
    private readonly repository: Repository<Event>,
  ) {}
  async create(createEventDto: CreateEventDto) {
    const entity = this.repository.create(createEventDto);
    return await this.repository.save(entity);
  }

  async saveList(list: CreateEventDto[]) {
    const entities = list.map((v) => this.repository.create(v));
    await this.repository.save(entities);
  }

  async findOne(id: number) {
    // return this.repository.findOne({
    //   where: { id },
    //   select: ['id', 'name', 'type', 'tournamentId', 'categoryId'],
    // });
    return this.repository
      .createQueryBuilder('event')
      .leftJoinAndSelect('event.stages', 'stages')
      .where('event.id = :id', { id })
      .select([
        'event.id',
        'event.name',
        'event.type',
        'event.tournamentId',
        'event.categoryId',
        'stages.id',
        'stages.name',
        'stages.type',
        'stages.stageOrderInEvent',
      ])
      .getOne();
  }

  async findWithCategoryAndTournamentByIds(ids: number[]) {
    return this.repository
      .createQueryBuilder('event')
      .leftJoinAndSelect('event.category', 'category')
      .leftJoinAndSelect('event.tournament', 'tournament')
      .where('event.id IN (:...ids)', { ids })
      .getMany();
  }

  async update(id: number, updateEventDto: CreateEventDto) {
    await this.repository.update(id, updateEventDto);
    return this.repository.findOne({ where: { id } });
  }

  async remove(id: number) {
    return await this.repository.delete(id);
  }
  async removeIds(ids: number[]) {
    return await this.repository.delete(ids);
  }

  async findByStageId(stageId: number) {
    const res = await this.repository
      .createQueryBuilder('event')
      .leftJoinAndSelect('event.stages', 'stages')
      .where('stages.id = :stageId', { stageId })
      // .leftJoinAndSelect('event.eventToPlayers', 'eventToPlayers')
      // .leftJoinAndSelect('eventToPlayers.player', 'player')
      // .leftJoinAndSelect('eventToPlayers.player2', 'player2')
      // .leftJoinAndSelect('eventToPlayers.team', 'team')
      .leftJoinAndSelect('stages.groups', 'groups')
      .leftJoinAndSelect('groups.matchInfos', 'matchInfos')
      .leftJoinAndSelect('matchInfos.playground', 'playground')
      .leftJoinAndSelect('matchInfos.homePlayer', 'homePlayer')
      .leftJoinAndSelect('matchInfos.awayPlayer', 'awayPlayer')
      .andWhere('matchInfos.subMatchId IS NULL')
      .leftJoinAndSelect('matchInfos.subMatchInfos', 'subMatchInfos')
      .leftJoinAndSelect('subMatchInfos.playground', 'subPlayground')
      .leftJoinAndSelect('subMatchInfos.homePlayer', 'subHomePlayer')
      .leftJoinAndSelect('subMatchInfos.awayPlayer', 'subAwayPlayer')
      .getOne();
    // res.eventToPlayers.forEach((v) => {
    //   if (v.player1Name) {
    //     v.player = { name: v.player1Name };
    //   }
    //   if (v.player2Name) {·
    //     v.player2 = { name: v.player2Name };
    //   }
    //   if (v.teamName) {
    //     v.team = { name: v.teamName };
    //   }
    // });
    return res;
  }

  async findByCategoryId(categoryId: number) {
    return this.repository
      .createQueryBuilder('event')
      .leftJoinAndSelect('event.category', 'category')
      .where('category.id = :categoryId', { categoryId })
      .leftJoinAndSelect('event.stages', 'stage')
      .leftJoinAndSelect('stage.stageEvents', 'stageEvent')
      .getMany();
  }
  async removeInIds(ids: number[]) {
    return await this.repository.delete(ids);
  }

  async findByIds(ids: number[]) {
    return await this.repository
      .createQueryBuilder('event')
      .where('event.id IN (:...ids)', { ids })
      .getMany();
  }

  async findForConfirmE2P(eventId: number, playerIds: number[]) {
    // 用于报名的查询
    return this.repository
      .createQueryBuilder('event')
      .where('event.id = :eventId', { eventId })
      .leftJoinAndSelect('event.eventToPlayers', 'eventToPlayers')
      .leftJoinAndSelect('event.playerSignups', 'playerSignups')
      .andWhere('playerSignups.id IN (:...playerIds)', { playerIds })
      .leftJoinAndSelect('playerSignups.subPlayerSignups', 'subPlayerSignups')
      .leftJoinAndSelect('subPlayerSignups.stageEvent', 'stageEvent')
      .andWhere('playerSignups.parentPlayerId IS NULL')
      .select([
        'event.id',
        'event.name',
        'event.type',
        'eventToPlayers.id',
        'eventToPlayers.registrationIndex',
        'eventToPlayers.stageOrderInEvent',
        'playerSignups',
        'stageEvent.id',
        'stageEvent.eventOrder',
        'stageEvent.type',
        'subPlayerSignups',
      ])
      .getOne();
  }
  async getByIdWithRelations(id: number) {
    return await this.repository.findOne({
      where: { id },
      relations: ['stages', 'eventToPlayers', 'playerSignups'],
    });
  }
  async getByIdWithStages(id: number) {
    return await this.repository.findOne({
      where: { id },
      relations: ['stages'],
    });
  }
  async checkFinish(id: number) {
    logger.info('finishEvent...', id);
    const { stages } = await this.getByIdWithStages(id);
    const isAllFinished = stages.every(
      (group) => group.status === StageStatusEnum.Finished,
    );
    if (isAllFinished) {
      await this.update(id, {
        id,
        status: EventStatusEnum.Finished,
      } as any);
    }
    logger.info('finishEvent...', id, isAllFinished);
    return isAllFinished;
  }
  findById(id: number) {
    return this.repository.findOne({
      where: { id },
    });
  }
}
